// #include "rattle.h"
// #include "shake.h"

#include "elemtab.h"
#include "rigid.hpp"

void rigid_type_table::parse(const char *condstr, elemtab_t *elemtab) {
  int cnt, ptr = 0;
  char cond[16];
  while (sscanf(condstr + ptr, "%s%n", cond, &cnt) == 1) {
    ptr += cnt;
    // shake_cond_t *cond_ent = esmd_list_get_slot(&shake_cond);
    elemstr itype, jtype, ktype;
    if (!strcmp(cond, "type")) {
      sscanf(condstr + ptr, "%s%n", itype, &cnt);
      ptr += cnt;
      int is_wildcard = 0;
      for (int i = 0; itype[i]; i++)
        if (itype[i] == '*') {
          itype[i] = 0;
          is_wildcard = 1;
          break;
        }
      if (!is_wildcard) {
        types[elemtab_get(elemtab, itype)] = 1;
      } else {
        int prefix_len = strlen(itype);
        for (auto &elem : *elemtab) {
          if (!strncmp(itype, elem.key, prefix_len)) {
            types[elem.val] = 1;
          }
        }
      }
    } else if (!strcmp(cond, "angle")) {
      sscanf(condstr + ptr, "%s%s%s%n", itype, jtype, ktype, &cnt);
      ptr += cnt;
      int ti = elemtab_get(elemtab, itype);
      int tj = elemtab_get(elemtab, jtype);
      int tk = elemtab_get(elemtab, ktype);
      angles[(tj * ntypes + ti) * ntypes + tk] = 1;
      angles[(tj * ntypes + tk) * ntypes + ti] = 1;
    } else if (!strcmp(cond, "bond")) {
      sscanf(condstr + ptr, "%s%s%n", itype, jtype, &cnt);
      ptr += cnt;
      int ti = elemtab_get(elemtab, itype);
      int tj = elemtab_get(elemtab, jtype);
      bonds[ti * ntypes + tj] = 1;
    } else if (!strcmp(cond, "exclude")) {
      sscanf(condstr + ptr, "%s%s%n", itype, jtype, &cnt);
      ptr += cnt;
      int ti = elemtab_get(elemtab, itype);
      int tj = elemtab_get(elemtab, jtype);
      bonds[ti * ntypes + tj] = -1;
    }
  }
}
#ifndef __sw_64__
void unconstrained_update(cellgrid_t *grid, real dtv, real dtfsq) {
  // real dtfsq = dtf * dtf;
  FOREACH_LOCAL_CELL(grid, ii, jj, kk, cell) {
    for (int i = 0; i < cell->natom; i++) {
      cell->shake_xuc[i] = cell->x[i] + cell->v[i] * dtv + cell->f[i] * dtfsq * cell->rmass[i];
    }
  }
}
#else
extern void unconstrained_update_sw(cellgrid_t *grid, real dtv, real dtfsq);
void unconstrained_update(cellgrid_t *grid, real dtv, real dtfsq) {
  // real dtfsq = dtf * dtf;
  unconstrained_update_sw(grid, dtv, dtfsq);
}
#endif
